﻿package code {
	
	import flash.display.Sprite;
	import flash.events.*;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.media.Sound;
	import flash.media.SoundChannel;
	import com.as3toolkit.events.KeyboarderEvent;
	import com.as3toolkit.ui.Keyboarder;
	import flash.ui.Keyboard;
	import code.Characters.*;
	import GUI.Title;
	import GUI.Select;
	import flash.text.TextField;
	import flash.text.TextFormat;
	import flash.text.AntiAliasType;
	import flash.filters.DropShadowFilter;
	import flash.text.Font;
	import flash.net.FileReference;
	
	public class Field extends Sprite {
		public var player1, player2:Player;
		var playerList:Array;
		
		var turn:int;
		
		var keyboardStuff:Keyboarder;
		
		var gameState:Array;  // acts as an enum
		var currentState:String;
		var currentScreen:Sprite;
		var title:Title;
		var characterSelect:CharacterSelect;
		
		var select:Select;
		// XML stuff
		var xml:XML = new XML();
		var xmlLoader:URLLoader = new URLLoader(); // XML Loader 
		var xmlLoader1:URLLoader = new URLLoader(); // XML Loader 
		var accModifier:Number;
		
		var animationDone, gameOver, attackAgain:Boolean;
		var drawCounter:int;
		var gb:GameBackground = new GameBackground();
		
		public var channel2:SoundChannel = new SoundChannel();
		public var externalSound:Sound;
		
		var videoTextField:VideoTextField = new VideoTextField();
		var comicTextField:ComicTextField = new ComicTextField();
		
		var battleTextField:TextField;  		// A Textfield that displays what is going on in battle
		var dmgToTake:Number 					// Damage done by the attacker to the defender
		var canBeHit:Boolean 					// Can the defender be hit?
		var gameIsOver:Boolean					// Whether the game is over
		var gameObjects:Array = new Array();	// Things to remove when resetting
		var cardArray:Array = new Array();
		var fileRef:FileReference = new FileReference();
		
		var atkerNP:Number = 1/4;
		var defNP:Number = 1/3;
		
		public function Field() {
			keyboardStuff = new Keyboarder(this.stage);
			
			////title = new Title();
			gameState = new Array("TitleMenu", "Instructions", "Setup", "Credits", "Game", "Pause", "End");

			playerList = new Array();

			//nerdTextField = new TextField();
			battleTextField = new TextField();
			init();
		}
		
		public function init(){
			currentState = Const.TITLE_MENU;
			playerList = new Array();
			
			xmlLoader.addEventListener(Event.COMPLETE, loadXML);
			xmlLoader.load(new URLRequest("videoGameNerd.xml"));
			xmlLoader1.addEventListener(Event.COMPLETE, loadXML);
			xmlLoader1.load(new URLRequest("comicBookNerd.xml"));
			turn = 1;
			animationDone = true;
			
			
			//title = new Title();
			//addChild(title);
			
			characterSelect = new CharacterSelect();
			addChild(characterSelect);
		}
		
		// starts sound 
		private function playMusic(i:int):void
		{
			var req:URLRequest;
			if(i == 0)
				req = new URLRequest("Ultimate Nerd Music/Preferable final/Battle Song.mp3");		
			else
				req = new URLRequest("Ultimate Nerd Music/Preferable final/Battle Song Repeat.mp3");		
    		externalSound = new Sound(req);
    		channel2 = externalSound.play();
    		channel2.addEventListener(Event.SOUND_COMPLETE, loopMusic);
		}
		
		// when background sound is done loop it
		private function loopMusic(e:Event):void
		{
    		if (channel2 != null)
    		{
        		channel2.removeEventListener(Event.SOUND_COMPLETE, loopMusic);
        		playMusic(1);
    		}
		}
		
		public function gameInit(){
			title.remove();
			removeChild(title);
			select = new Select(player1, player2);
			
			addChild(select);
			currentState = Const.SETUP;
		}
		
		public function gameInit2(){
			gameIsOver = false;
			gameOver = false;
			drawCounter = 0;
			animationDone = true;
			select.remove();
			removeChild(select);
			
			// sets up initial player location values
			player1.x = 200;
			player1.y = 220;
			
			player2.x = 1000;
			player2.y = 200;
			
			if(turn == 1)
			player1.IsAttacking = true;  // sets up one player to attack first
			else
			player2.IsAttacking = true;
						
			playerList.push(player1);
			playerList.push(player2);
			
			playMusic(0);
			addChild(gb);
			addChild(player1);
			addChild(player2);
			gameObjects.push(gb);
			gameObjects.push(player1);
			gameObjects.push(player2);
			
			player1.Gui.name_txt.text = "P1";
			player1.Gui.hp_txt.text = player1.Hp;
			player1.Gui.np_txt.text = player1.Mana;
			
			player1.Gui.first_txt.text = "Q:Stored";
			player1.Gui.second_txt.text = "W:Basic";
			player1.Gui.third_txt.text = "E:Hand";
			
			videoTextField.textField.text = "ATTACK!";
			videoTextField.x = player1.Gui.x;
			videoTextField.y = player1.Gui.y + 70;
			addChild(videoTextField);
			gameObjects.push(videoTextField);
			
			comicTextField.textField.text = "DEFENSE!";
			comicTextField.x = player2.Gui.x + 980;
			comicTextField.y = player2.Gui.y + 70;
			addChild(comicTextField);
			gameObjects.push(comicTextField);
			
			// Set up the status text
			var font:Font = new Font1();
			battleTextField.text = "";
			battleTextField.x = 240;	// Values are hard-coded: change to be relative to stage size
			battleTextField.y = 180;
			battleTextField.width = 400;
			battleTextField.embedFonts = true;
			battleTextField.defaultTextFormat = new TextFormat(font.fontName, null, 0xffffff, null, null, null, null, null, "center");
			battleTextField.filters = [new DropShadowFilter(4, 45, 0x000000, 1.0, 0, 0)];
			battleTextField.wordWrap = true;
			battleTextField.scaleX = 2;
			battleTextField.scaleY = 2;
			addChild(battleTextField);
			addChild(player1.Gui);
			gameObjects.push(battleTextField);
			gameObjects.push(player1.Gui);
			
			// Move Player 2
			player2.Gui.name_txt.text = "P2";
			
			player2.Gui.hp_txt.text = "" + player2.Hp;
			player2.Gui.np_txt.text = "" + player2.Mana;
			
			player2.Gui.first_txt.text = "U:Stored";
			player2.Gui.second_txt.text = "I:Basic";
			player2.Gui.third_txt.text = "O:Hand";
			player2.Gui.x += 640;
			
			videoTextField.alpha = 1;
			comicTextField.alpha = 1;
			
			addChild(player2.Gui);
			gameObjects.push(player2.Gui);
			
			addEventListener(Event.ENTER_FRAME, update);
			addEventListener(Event.ENTER_FRAME, drawGame);
			Keyboarder.Instance.addEventListener(KeyboarderEvent.FIRST_PRESS, pressed);
		}
		
		public function loadXML(e:Event){
			xml = new XML(e.target.data);
			if(xml.@name == "videoGame"){
				player1 = new VideoGameNerd(xml, 1);  // fix later to make this so it works for both player
			}
			else if(xml.@name == "comicBook"){
				player2 = new ComicBookNerd(xml, 2);
				
				if(player1.Speed >= player2.Speed)
					turn = 1;
				else
				turn = 2;
			}
		}
		
		public function update(e:Event):void{
			if(animationDone)
				checkDamage();
			if(gameOver)
				destroy();
		}
		
		public function drawGame(e:Event):void{
			if(!animationDone)
				doGame();
		}
		
		public function doGame(){
			var attacker:Player;
			var defender:Player;

			if(turn == 2){  // means that they will be defending next turn
				attacker = player1;
				defender = player2;
			}
			else{
				attacker = player2;
				defender = player1;
			}
			if(drawCounter == 0){
				var playerName:String;
				if (attacker.PlayerName == "videoGame")
					playerName = "Video Game Nerd";
				else if (attacker.PlayerName == "comicBook")
					playerName = "Comic Book Nerd";
				
				if(attacker == player1)
					gb.gotoAndPlay("attackL");
				else if(attacker == player2)
					gb.gotoAndPlay("attackR");
				attacker.x = (stage.stageWidth / 2) - 100;
				attacker.y = (stage.stageHeight /2) - 100;
				defender.x = -200;
				defender.y = -200;
				attacker.gotoAndStop("attack");
				
				// Update battle information
				battleTextField.text = playerName + " uses " + attacker.CardUsing.CardName + "! ";
				if(attacker.CardUsing.Type == "attack" || attacker.CardUsing.Type == "attackN")
					if(canBeHit && dmgToTake != 0)
				 	  battleTextField.appendText(dmgToTake + " damage dealt! ");
				if (attacker.CardUsing.Type == "item"){
					addItemStatus(attacker, true);
				}
				if ((int)(Math.ceil((atkerNP) * dmgToTake)) > 0 && canBeHit)
					battleTextField.appendText(playerName + " gets " + (int)(Math.ceil((atkerNP) * dmgToTake)) + " Nerdiness!");
				
			}
			else if(drawCounter == 100){
				var playerName:String;
				if (defender.PlayerName == "videoGame")
					playerName = "Video Game Nerd";
				else if (defender.PlayerName == "comicBook")
					playerName = "Comic Book Nerd";
				
				gb.gotoAndStop("defense");
				defender.x = (stage.stageWidth / 2) - 100;
				defender.y = (stage.stageHeight /2) - 100;
				attacker.x = -200;
				attacker.y = -200;
				defender.gotoAndStop("defense");
				
				// Update battle information
				battleTextField.text = playerName + " uses " + defender.CardUsing.CardName + "! ";
				if(attacker.CardUsing.Type != "item" && (!canBeHit || dmgToTake == 0))
				 	  battleTextField.appendText("Attack Avoided");
				if (defender.CardUsing.Type == "item"){
					addItemStatus(defender, true);
				}
				if ((int)(Math.ceil((defNP) * dmgToTake)) > 0 && canBeHit)
					battleTextField.appendText(playerName + " gets " + (int)(Math.ceil((defNP) * dmgToTake)) + " Nerdiness!");
			}
			else if(drawCounter == 200){
				
				if(checkLose()){
					animationDone = true;
					gameOver = true;
					return;
				}
				
				animationDone = true;
				player1.gotoAndPlay("normal");
				player1.x = 200;
				player1.y = 220;
				player2.x = 1000;
				player2.y = 200;
				player2.gotoAndPlay("normal");
				gb.gotoAndPlay("normal");
				
				// Reset battle information
				battleTextField.text = "";
			
				
				// text field stuff
				videoTextField.alpha = 1;
				comicTextField.alpha = 1;
			}
			drawCounter++;
		}
		
		/**
		 * Add Item Effects to the displayed battle animation
		 * during the attack and defense phases
		 * @param	p			The player that is using the item
		 * @param	attacking	Whether the incoming player is attacking
		 * @author	Erik Buchholz
		 */
		private function addItemStatus(p:Player, attacking:Boolean){
			// Get the modification and Player name
			var mod:Number = p.CardUsing.Modifier;
			var playerName:String;
			if (p.PlayerName == "videoGame")
				playerName = "Video Game Nerd";
			else if (p.PlayerName == "comicBook")
				playerName = "Comic Book Nerd";
			
			// Switch on the effect of the card and append the appropriate message
			switch (p.CardUsing.Effect){
				case "pwr":
					battleTextField.appendText(playerName + " is powered up! ");
					break;
				case "ner":
					battleTextField.appendText(playerName + " gains " + mod + " Nerdiness! ");
					break;
				case "nerG":
					if (attacking){
						battleTextField.appendText(playerName + " can attack once more! ");
					}
					break;
				case "atG":
					battleTextField.appendText(playerName + " gains " + mod + " Attack next Attack Phase! ");
					break;
				case "adG":
					battleTextField.appendText(playerName + " gains " + mod + " Attack and Defense for 1 turn! ");
					break;
				case "defP":
					battleTextField.appendText(" Opponent's defense is lowered by " + mod + " for 3 turns! ");
					break;
				case "atkP":
					battleTextField.appendText(" Opponent is poisoned for 3 turns! ");
					break;
				case "hp":
					battleTextField.appendText(playerName + " gains " + mod + " Health! ");
					break;
				default:
					break;
			
			}
		}
		
		/*
		// checks for damage done
		// order is:
		// do Modifiers
		// defending player item check
		// defending player defense check
		// attacking player item check
		// attacking player attack check
		// deals damage*/
		public function checkDamage():void{
			var p1, p2:Player;
			player1.AttackAgain = false;
			player2.AttackAgain = false;
		
			
			playerList[0] = player1;
			playerList[1] = player2;
			
			if(turn == 1){
				p1 = playerList[0];  // based on turn, switches "whos on first"
				p2 = playerList[1];
			}
			else{
				p1 = playerList[1];
				p2 = playerList[0];
			}
			
			var newText1:String = "";
				var newText2:String = "";
					
				for each (var newThing:Modifier in player1.Modifiers){
					newText1 += String(newThing.Stat + "\n ");
				}
				
				for each (var newer:Modifier in player2.Modifiers){
					newText2 += String(newer.Stat + "\n ");
				}
				
				if(!player1.AttackAgain){
					if(player1 == p1)
						videoTextField.textField.text = "ATTACK!"+ "\n " + newText1;
					else 
						videoTextField.textField.text = "DEFENSE!" + "\n " + newText1;
				}
				if(!player2.AttackAgain){
					if(player2 == p1)
						comicTextField.textField.text = "ATTACK!"+ "\n " + newText2;
					else 
						comicTextField.textField.text = "DEFENSE!" + "\n " + newText2;
				}
				
				if(player1.MoveComplete){
					videoTextField.textField.height = 1000;
					videoTextField.textField.text = "Move Complete" + "\n " + newText1;
				}
				
				if(player2.MoveComplete){
					comicTextField.textField.height = 1000;
					comicTextField.textField.text = "Move Complete"  + "\n " + newText2;
				}
			
			if(p1.MoveComplete && p2.MoveComplete){
				videoTextField.alpha = 0;
				comicTextField.alpha = 0;
				
				dmgToTake = 0;
				canBeHit = true;
				accModifier = 0;
				
				// checks to see if they have anything to modify
				checkModifiers(p1);
				checkModifiers(p2);
				
				if(checkIfHit(p2)){
					if(p2.CardUsing != null && p2.CardUsing.Type == "item"){
						checkItem(p2);
					}
					else if(p2.CardUsing != null && p2.CardUsing.Type == "defense"){  // checks for the defense modifier
						if(p2.CardUsing.Effect == "def"){	// if checks for defense effect
							p2.TempDefense += p2.CardUsing.Modifier;
						}
						else if(p2.CardUsing.Effect == "accS"){
							canBeHit = false;	// currently all accuracy self allows for avoidance of attacks
						}
						else if(p2.CardUsing.Effect == "accO"){
							accModifier = p2.CardUsing.Modifier;  // sets the modifier for checking if player1 can hit
						}
					}
				}
				if(checkIfHit(p1)){
					if(p1.CardUsing.Type == "item"){
						checkItem(p1);
					}

					else if(p1.CardUsing.Type == "attack" || p1.CardUsing.Type == "attackN"){
						dmgToTake = (p1.CardUsing.Modifier + p1.Attack + p1.TempAttack) - (p2.Defense + p2.TempDefense); // does the defense - damage
						if(dmgToTake <= 0){
							dmgToTake = 1; // damage is always at least 1
						}
					}

				}
				if(canBeHit){
					p2.Hp -= dmgToTake;
					p1.Mana += Math.ceil((atkerNP) * dmgToTake);
					p2.Mana += Math.ceil((defNP) * dmgToTake);
				}
				
				p1.MoveComplete = false;
				p2.MoveComplete = false;
				p1.switchPhase();
				p2.switchPhase();
				
				animationDone = false;
				drawCounter = 0;
				
				if(p1.AttackAgain){
					p2.MoveComplete = true;
					p2.CardUsing = null;
				}
				else if(p2.AttackAgain){
					p1.MoveComplete = true;
					p1.CardUsing = null;
				}
				else{
					if(turn == 1){
						turn++;
					}
					else if(turn == 2){
						turn--;
					}
					
				}
				
				// Update stuff
				player1.Gui.hp_txt.text = ""+player1.Hp;
				player1.Gui.np_txt.text = ""+player1.Mana;
				
				player2.Gui.hp_txt.text = ""+player2.Hp;
				player2.Gui.np_txt.text = ""+player2.Mana;
				
				cardArray.push(player1.CardUsing);
				cardArray.push(player2.CardUsing);
				
					if(player1 == p1)
						videoTextField.textField.text = "DEFENSE!"+ "\n " + newText1;
					else 
						videoTextField.textField.text = "ATTACK!" + "\n " + newText1;
						
					if(player2 == p1)
						comicTextField.textField.text = "DEFENSE!"+ "\n " + newText2;
					else 
						comicTextField.textField.text = "ATTACK!" + "\n " + newText2;
				
			}
		}
		
		
		// checks the modifiers and adjusts the stats accordingly
		public function checkModifiers(p1:Player){
			p1.TempAttack = 0;
			p1.TempDefense = 0;
			for(var i:int = 0; i < p1.Modifiers.length; i++){
				if(p1.IsAttacking && p1.Modifiers[i].Stat == "attack"){ // checks to see if phase to buff, if it is, calls the modify method
					if(p1.Modifiers[i].modify(p1)){
						p1.Modifiers.splice(i, 1);
						i--;
					}
				}
				else if(!p1.IsAttacking && p1.Modifiers[i].Stat == "defense"){  // if defense phase, modify defense
					if(p1.Modifiers[i].modify(p1)){
						p1.Modifiers.splice(i, 1);
						i--;
					}
				}
				else if(p1.Modifiers[i].Stat == "hp"){
					if(p1.Modifiers[i].modify(p1)){
						p1.Modifiers.splice(i, 1);
						i--;
					}
				}
				else if(p1.Modifiers[i].Stat == "pwr"){
					if(p1.Modifiers[i].modify(p1)){
						p1.PoweredUp = false;
						p1.Modifiers.splice(i, 1);
						i--;
					}
				}
			}
		}
		
		public function checkItem(p1:Player){
			if(p1.CardUsing.Effect == "ner"){
				p1.Mana += p1.CardUsing.Modifier;
			}
			else if(p1.CardUsing.Effect == "nerG"){
				p1.Mana += p1.CardUsing.Modifier;
				attackAgain = true;
			}
			else if(p1.CardUsing.Effect == "atG"){
				p1.Modifiers.push(new Modifier("attack", 2, p1.CardUsing.Modifier));
			}
			else if(p1.CardUsing.Effect == "adG"){
				p1.Modifiers.push(new Modifier("attack", 2, p1.CardUsing.Modifier));
				
				// if they are in the defense phase, it affects them currently.  Otherwise
				if(!p1.IsAttacking)
					p1.TempDefense = p1.CardUsing.Modifier;
				else
					p1.Modifiers.push(new Modifier("defense", p1.CardUsing.Modifier, 1));
			}
			else if(p1.CardUsing.Effect == "atkP"){ // "poison" effect that lasts for three turns
				p1.Modifiers.push(new Modifier("hp", 6, p1.CardUsing.Modifier));
			}
			else if(p1.CardUsing.Effect == "defP"){
				p1.Modifiers.push(new Modifier("defense", 2, p1.CardUsing.Modifier));
			}
			else if(p1.CardUsing.Effect == "hp"){
				p1.Hp += p1.CardUsing.Modifier;
			}
			else if(p1.CardUsing.Effect == "pwr"){
				p1.PoweredUp = true;
				p1.Modifiers.push(new Modifier("pwr", 4, 0));
			}
		}
		
				
		// checks if hit
		public function checkIfHit(p1:Player):Boolean{
			var randomAmount = Math.random();
			var hit:Boolean;
			if(randomAmount > p1.Accuracy - p1.CardUsing.Accuracy - accModifier){
				hit = true;
			}
			else{
				hit = false;
			}
			return hit;
		}
		
		// checks to see which player pressed the keys
		public function pressed(e:KeyboarderEvent){
			if(animationDone && !gameIsOver){
				if(!player1.MoveComplete && (e.keyCode == 65 || e.keyCode == 68 || e.keyCode == 87 || e.keyCode == 83 || e.keyCode == 69 || e.keyCode == 81 || e.keyCode == 82 || e.keyCode == 70)){
					player1.Gui.selectCard(e.keyCode);
				}
				else if(!player2.MoveComplete && (e.keyCode == 85 || e.keyCode == 73 || e.keyCode == 79 || e.keyCode == 80 || e.keyCode == 74 || e.keyCode == 76 || e.keyCode == 75 || e.keyCode == 186)){
					player2.Gui.selectCard(e.keyCode);
				}
			}
			if(gameIsOver && e.keyCode == Keyboard.B){
				for (var a:int = 0; a < gameObjects.length; a++){
					removeChild(gameObjects[a]);
				}
				gameObjects.splice(0, gameObjects.length);
				Keyboarder.Instance.removeEventListener(KeyboarderEvent.FIRST_PRESS, pressed);
				init();
				gb.gotoAndPlay("normal");
				stage.focus = this;
			}
		}
		
		// checks to see if the game has ended
		public function checkLose():Boolean{
			if(player1.Hp <= 0 || player2.Hp <= 0){
				// game over
				gb.gotoAndStop("win");
				channel2.stop();
				channel2.removeEventListener(Event.SOUND_COMPLETE, loopMusic);
				var winner:Player;
				player2.Hp <= 0 ? winner = player1 : winner = player2;
				winner.x = (stage.stageWidth / 2) - 100;
				winner.y = (stage.stageHeight /2) - 100;
				winner.gotoAndStop("attack");
				var loser:Player;
				player1.Hp <= 0 ? loser = player1 : loser = player2;
				loser.x = -200;
				loser.y = -200;
				battleTextField.text = "Winner!\nPress B to continue.";
				gameIsOver = true;
				stage.focus = this;
				save();
				cardArray = new Array();
				return true;
			}
			return false;
		}
		
		public function save(){
			var winner:String;
			var winnerHp:int;
			if(player1.Hp <= 0){
				winner = "Player 2";
				winnerHp = player2.Hp;
			}
			else{
				winner = "Player 1";
				winnerHp = player1.Hp;
			}
			var dat:String = "Winner: " + winner + " Winner Hp: " + winnerHp;
			for each(var c:Card in cardArray){
				dat += "\n" + " Name: " + c.CardName + " Mana Cost: " + c.ManaCost + " Effect: " + c.Effect + " Modifier: " + c.Modifier;
			}
			fileRef.save(dat,"game1.txt");
		}
		public function destroy(){
			removeEventListener(Event.ENTER_FRAME, update);
			removeEventListener(Event.ENTER_FRAME, drawGame);
		}
		
		
	}
	
}
